use model_graph_common::config::get_peer_config;
use serde::{Serialize, Serializer};
use std::{collections::HashMap, sync::Mutex};
use tauri::{command, AppHandle, Runtime, State, Window};

use model_graph_common::{
    transport::http::http_download_file,
    utils::{
        read_bytes_from_pathbuf,
        zip::{compress_dir, compress_file, extract_v8_to_fs},
    },
};
use model_graph_types::{
    assistant::{
        chat::{ChatMessage, ChatOptions},
        shell::{
            BatchScriptRequestMessage, ShellRequestMessage, ShellRequestOptions,
            ShellResponseMessage,
        },
        tts::{TtsRequestMessage, TtsRequestOptions, TtsResponseMessage},
    },
    connector::{Connector, ExecuteOptions, QueryOptions},
    database::{DataSource, DatabaseType},
    modeling::Value,
    transform::{DataTransformOptions, DataTransformUnit, DataTransformer},
};

use data_transform::DefaultDataTransformer;
use serde_json::Value as JsonValue;
use std::path::PathBuf;
use union_connector::UnionConnector;

use super::ContextState;
use super::Error;
use super::Result;

#[command]
pub async fn home_path<R: Runtime>(_app: AppHandle<R>, _window: Window<R>) -> String {
    let home_path = model_graph_common::utils::rrg01_home_path().expect("获取程序目录失败!");

    format!("{}", home_path.to_str().expect("获取程序目录失败!"))
}

#[command]
pub async fn peer_id<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
) -> Result<(String, String)> {
    //获取到本机的peer_id
    let peer_config = get_peer_config().await?;
    //

    Ok((peer_config.peer_id, String::new()))
}

#[command]
pub async fn peer_login<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    token: String,
) -> Result<()> {
    let result = model_graph_peer::peer_login(&token).await;
    //

    Ok(())
}

#[command]
pub async fn peer_status<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
) -> Result<String> {
    let result = model_graph_peer::peer_status().await?;
    //
    Ok(serde_json::to_string(&result).map_err(|err| anyhow::anyhow!("{}", err))?)
}

#[command]
pub async fn peer_assistant_chat<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    messages: Vec<ChatMessage>,
    options: ChatOptions,
) -> Result<Vec<ChatMessage>> {
    let result = model_graph_peer::assistant::assistant_local_chat(messages, options).await?;
    //
    Ok(result)
}

#[command]
pub async fn peer_assistant_sv2tts<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    messages: TtsRequestMessage,
    local_path: String,
    options: TtsRequestOptions,
) -> Result<()> {
    // let result =
    //     model_graph_peer::assistant::assistant_local_sv2tts(messages, local_path, options).await?;
    // //
    Ok(())
}

#[command]
pub async fn peer_assistant_shell<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    messages: ShellRequestMessage,
    options: ShellRequestOptions,
) -> Result<ShellResponseMessage> {
    let result = model_graph_peer::assistant::assistant_local_shell(messages, options).await?;
    //
    Ok(result)
}

#[command]
pub async fn peer_assistant_batch_script<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    messages: BatchScriptRequestMessage,
    options: ShellRequestOptions,
) -> Result<ShellResponseMessage> {
    let result =
        model_graph_peer::assistant::assistant_local_batch_script(messages, options).await?;
    //
    Ok(result)
}

#[command]
pub async fn channel_pubsub_publish<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    topic: String,
    subscribers: Vec<String>,
) -> Result<()> {
    let result = model_graph_channel::pubsub::publish(&topic, subscribers).await?;
    //
    Ok(result)
}

#[command]
pub async fn channel_pubsub_publish_message<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    topic: String,
    message: String,
) -> Result<()> {
    let result = model_graph_channel::pubsub::publish_message(&topic, message).await?;
    //
    Ok(result)
}

#[command]
pub async fn channel_pubsub_subscribe<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    topic: model_graph_types::channel::pubsub::Topic,
) -> Result<()> {
    let result = model_graph_channel::pubsub::subscribe(topic).await?;
    //
    Ok(result)
}

#[command]
pub async fn channel_uicmd_response<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    request_id: u32,
    message: String,
) -> Result<()> {
    let result =
        model_graph_channel::data_channels::ui_request::put_response(request_id, message).await?;
    //
    Ok(result)
}

#[command]
pub async fn channel_uicmd_remote_request<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    peer_id: String,
    message: String,
    timout: Option<u32>,
) -> Result<String> {
    let timeout = timout.map_or(30000u64, |t| t as u64);
    let result =
        model_graph_channel::data_channels::ui_request::remote_request(peer_id, message, timeout)
            .await?;
    //
    Ok(result)
}

#[command]
pub async fn file_download<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    url: String,
    file: String,
) -> Result<bool> {
    let _ = http_download_file(&url, file.as_str()).await?;
    //
    Ok(true)
}

#[command]
pub async fn file_unzip<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    zip_file: String,
    file_path: String,
) -> Result<bool> {
    //读取解压文件内容
    let path = PathBuf::from(zip_file);
    let zip_file: Vec<u8> = read_bytes_from_pathbuf(&path)?;
    extract_v8_to_fs(&zip_file, file_path.as_str())?;
    Ok(true)
}

#[command]
pub async fn file_compress_dir<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    file_path: String,
    zip_file: String,
) -> Result<bool> {
    //读取解压文件内容
    compress_dir(file_path.as_str(), zip_file.as_str())?;
    Ok(true)
}

#[command]
pub async fn file_compress_file<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    file_path: String,
    zip_file: String,
) -> Result<bool> {
    //读取解压文件内容
    compress_file(file_path.as_str(), zip_file.as_str())?;
    Ok(true)
}